﻿
using Microsoft.Windows.Shell;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using UBCon.Ribbon;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using UBCon.Core;
using UBCon.Core.Commands;
using UBCon.Core.Utilities;
using UBCon.Core.Enums;
using System.Diagnostics;
using System.Windows.Controls.Primitives;


namespace UBCon.Ribbon
{
    /// <summary>
    /// Provides the ability to create, configure, show and manage the lifetime of windows and dialog boxes.
    /// </summary>
    [TemplatePart(Name = AppMenuPresenterName, Type = typeof(ContentPresenter))]
    //[TemplatePart(Name = ContentDecoratorName, Type = typeof(AdornerDecorator))]
    [TemplatePart(Name = PART_IconName, Type = typeof(Image))]
    [TemplatePart(Name = contextualHeaderPanelName, Type = typeof(Canvas))]
    [TemplatePart(Name = footerContentPresenterName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = rootPanelName, Type = typeof(Grid))]
    [TemplatePart(Name = QAToolbarHostName, Type = typeof(ContentPresenter))]
    [TemplatePart(Name = PART_TitleLocatorName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = PART_CaptionButtonsHolderName, Type = typeof(StackPanel))]
    public partial class RibbonWindow : Window
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
        #region Constructors

        /// <summary>
        /// Default static constructor.
        /// </summary>
        static RibbonWindow()
        {
            Type ownerType = typeof(RibbonWindow);
            DefaultStyleKeyProperty.OverrideMetadata(ownerType,
                 new FrameworkPropertyMetadata(ownerType)
                 );

            TitleProperty.OverrideMetadata(ownerType, new FrameworkPropertyMetadata(
                string.Empty,
                new PropertyChangedCallback(OnTitleChanged)));

            WindowStateProperty.OverrideMetadata(ownerType, 
                new FrameworkPropertyMetadata(WindowState.Normal,
                        new PropertyChangedCallback(OnWindowStateChanged),
                        new CoerceValueCallback(CoerceWindowState)));
            ResizeModeProperty.OverrideMetadata(ownerType, 
                new FrameworkPropertyMetadata(ResizeMode.CanResize,
                        new PropertyChangedCallback(OnResizeModeChanged), 
                        new CoerceValueCallback(CoerceResizeMode)));

        }

        /// <summary>
        /// Initializes a new instance of the UBCon.Ribbon.RibbonWindow class.
        /// </summary>
        public RibbonWindow()
            : base()
        {
            SetHook();
            //Console.WriteLine(System.Windows.SystemParameters.ResizeFrameVerticalBorderWidth);
            //Here we register all commands.
            RegisterCommands();

            OpenCloseAppMenuCommand = new Command(OnOpenCloseApplicationMenuCommandExecuted);
            SizeChanged += OnWindowSizeChanged;

            QAToolbarItems = new ObservableCollection<UIElement>();
            QAToolbarItems.CollectionChanged += OnQAToolbarItemsCollectionChanged;

            CaptionItems = new ObservableCollection<UIElement>();
            CaptionItems.CollectionChanged += OnCaptionItemsCollectionChanged;

            HiddenItems = new ObservableCollection<UIElement>();
            HiddenItems.CollectionChanged += OnHiddenItemsCollectionChanged;

            Loaded += OnWindowLoaded;
            
        }
        
        #endregion

        //------------------------------------------------------
        //
        //  Properties
        //
        //------------------------------------------------------
        #region Properties

        /// <summary>
        /// Gets or sets the theme that can be applied to UBCon.Ribbon.RibbonWindow.
        /// </summary>
        public WindowTheme Theme
        {
            get { return (WindowTheme)GetValue(ThemeProperty); }
            set { SetValue(ThemeProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.Theme dependency property.
        /// </summary>
        public static readonly DependencyProperty ThemeProperty =
            DependencyProperty.Register("Theme", typeof(WindowTheme), typeof(RibbonWindow), 
            new FrameworkPropertyMetadata(WindowTheme.Default, 
                FrameworkPropertyMetadataOptions.AffectsMeasure, 
                OnThemeChanged,
                CoerceTheme));

        /// <summary>
       /// Gets or sets a margin value for visual child when window is maximized.
       /// </summary>
        internal Thickness WindowResizeFrame
        {
            get { return (Thickness)GetValue(WindowResizeFrameProperty); }
            set { SetValue(WindowResizeFrameProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.WindowResizeFrame dependency property.
        /// </summary>
        internal static readonly DependencyProperty WindowResizeFrameProperty =
            DependencyProperty.Register("WindowResizeFrame", typeof(Thickness), typeof(RibbonWindow));

        /// <summary>
        /// Gets or sets margin of caption panel when Theme is Classic.
        /// </summary>
        internal Thickness TitleBarMargin
        {
            get { return (Thickness)GetValue(TitleBarMarginProperty); }
            set { SetValue(TitleBarMarginProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.CaptionPanelMargin dependency property.
        /// </summary>
        internal static readonly DependencyProperty TitleBarMarginProperty =
            DependencyProperty.Register("TitleBarMargin", typeof(Thickness), typeof(RibbonWindow));

        /// <summary>
        /// Gets or sets a collection of UIElement which are presented in the caption of the window.
        /// This is a dependency property.
        /// </summary>
        public ObservableCollection<UIElement> CaptionItems
        {
            get { return (ObservableCollection<UIElement>)GetValue(CaptionItemsProperty); }
            set { SetValue(CaptionItemsProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.CaptionItems dependency property.
        /// </summary>
        public static readonly DependencyProperty CaptionItemsProperty =
            DependencyProperty.Register("CaptionItems", typeof(ObservableCollection<UIElement>), typeof(RibbonWindow),
            new PropertyMetadata((ObservableCollection<UIElement>)null));

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.RibbonWindow.EnableDefaulStyle attached property for the 
        /// given dependency object.
        /// </summary>
        public static bool GetEnableDefaulStyle(DependencyObject obj)
        {
            return (bool)obj.GetValue(EnableDefaulStyleProperty);
        }

        /// <summary>
        /// Sets the value of the UBCon.Ribbon.RibbonWindow.EnableDefaulStyle attached property for the 
        /// given dependency object.
        /// </summary>
        public static void SetEnableDefaulStyle(DependencyObject obj, bool value)
        {
            obj.SetValue(EnableDefaulStyleProperty, value);
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonWindow.EnableDefaulStyle attached property.
        /// </summary>
        public static readonly DependencyProperty EnableDefaulStyleProperty =
            DependencyProperty.RegisterAttached("EnableDefaulStyle", typeof(bool), typeof(RibbonWindow),
            new PropertyMetadata(false, new PropertyChangedCallback(OnEnableDefaulStylePropertyChanged)));

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.RibbonWindow.IsCollapsable attached property for the 
        /// given dependency object.
        /// </summary>
        public static bool GetIsCollapsable(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsCollapsableProperty);
        }

        /// <summary>
        /// Sets the value of the UBCon.Ribbon.RibbonWindow.IsCollapsable attached property for the 
        /// given dependency object.
        /// </summary>
        public static void SetIsCollapsable(DependencyObject obj, bool value)
        {
            obj.SetValue(IsCollapsableProperty, value);
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonWindow.IsCollapsable attached property.
        /// </summary>
        public static readonly DependencyProperty IsCollapsableProperty =
            DependencyProperty.RegisterAttached("IsCollapsable", typeof(bool), typeof(RibbonWindow),
            new PropertyMetadata(true));

        /// <summary>
        /// Gets or sets UIElement collection for Quick access toolbar.
        /// </summary>
        public ObservableCollection<UIElement> QAToolbarItems
        {
            get { return (ObservableCollection<UIElement>)GetValue(QAToolbarItemsProperty); }
            set { SetValue(QAToolbarItemsProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.QAToolbarItems dependency property.
        /// </summary>
        public static readonly DependencyProperty QAToolbarItemsProperty =
            DependencyProperty.Register("QAToolbarItems", typeof(ObservableCollection<UIElement>), typeof(RibbonWindow), new PropertyMetadata(null));

        /// <summary>
        /// Gets or sets footer content of the window.
        /// This is a dependenncy property.
        /// </summary>
        [Bindable(true),
        Browsable(false),
        ReadOnly(false)]
        public object Footer
        {
            get { return (object)GetValue(FooterProperty); }
            set { SetValue(FooterProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.Footer dependency property.
        /// </summary>
        public static readonly DependencyProperty FooterProperty =
            DependencyProperty.Register("Footer", typeof(object), typeof(RibbonWindow), new FrameworkPropertyMetadata(null));

        [Bindable(true),
        Browsable(true),
        ReadOnly(false),
        Category("Appearance")]
        public bool IsMinimizeButtonEnabled
        {
            get { return (bool)GetValue(IsMinimizeButtonEnabledProperty); }
            set { SetValue(IsMinimizeButtonEnabledProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsMinimizeButtonEnabled.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsMinimizeButtonEnabledProperty =
            DependencyProperty.Register("IsMinimizeButtonEnabled", typeof(bool), typeof(RibbonWindow),
            new FrameworkPropertyMetadata(true));

        [Bindable(true),
        Browsable(true),
        ReadOnly(false),
        Category("Appearance")]
        public bool IsMaximizeButtonEnabled
        {
            get { return (bool)GetValue(IsMaximizeButtonEnabledProperty); }
            set { SetValue(IsMaximizeButtonEnabledProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsMaximizeButtonEnabled.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsMaximizeButtonEnabledProperty =
            DependencyProperty.Register("IsMaximizeButtonEnabled", typeof(bool), typeof(RibbonWindow),
            new FrameworkPropertyMetadata(true));

        public bool IsCloseButtonEnabled
        {
            get { return (bool)GetValue(IsCloseButtonEnabledProperty); }
            set { SetValue(IsCloseButtonEnabledProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsCloseButtonEnabled.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsCloseButtonEnabledProperty =
            DependencyProperty.Register("IsCloseButtonEnabled", typeof(bool), typeof(RibbonWindow), new PropertyMetadata(true));

        /// <summary>
        /// Gets or sets instance of ApplicationMenu class. 
        /// This is a dependency property.
        /// </summary>
        internal ApplicationMenu ApplicationMenu
        {
            get { return (ApplicationMenu)GetValue(ApplicationMenuProperty); }
            set { SetValue(ApplicationMenuProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.ApplicationMenu dependency property.
        /// </summary>
        internal static readonly DependencyProperty ApplicationMenuProperty =
            DependencyProperty.Register("ApplicationMenu", typeof(ApplicationMenu), typeof(RibbonWindow),
            new FrameworkPropertyMetadata((ApplicationMenu)null,
                new PropertyChangedCallback(RibbonWindow.OnApplicationMenuPropertyChanged)));

        internal Command OpenCloseAppMenuCommand
        {
            get { return (Command)GetValue(OpenCloseAppMenuCommandProperty); }
            set { SetValue(OpenCloseAppMenuCommandProperty, value); }
        }

        // Using a DependencyProperty as the backing store for OpenCloseAppMenuCommand.  This enables animation, styling, binding, etc...
        internal static readonly DependencyProperty OpenCloseAppMenuCommandProperty =
            DependencyProperty.Register("OpenCloseAppMenuCommand", typeof(Command), typeof(RibbonWindow),
            new FrameworkPropertyMetadata(null));

        /// <summary>
        /// Gets a boolean value indicating whether menu is open or not.
        /// This is a dependency property.
        /// </summary>
        [Bindable(true),
        ReadOnly(true)]
        public bool IsApplicationMenuOpen
        {
            get { return (bool)GetValue(IsApplicationMenuOpenProperty); }
            internal set { SetValue(IsApplicationMenuOpenProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.IsApplicationMenuOpen dependency property.
        /// </summary>
        public static readonly DependencyProperty IsApplicationMenuOpenProperty =
            DependencyProperty.Register("IsApplicationMenuOpen", typeof(bool), typeof(RibbonWindow),
                    new FrameworkPropertyMetadata(false,
                        FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                        new PropertyChangedCallback(RibbonWindow.OnIsApplicationMenuOpenPropertyChanged),
                        new CoerceValueCallback(RibbonWindow.CoerceIsApplicationMenuOpenProperty)));

        /// <summary>
        /// Gets or sets quick access toolbar control.
        /// This is a dependency property.
        /// </summary>
        [Bindable(false), ReadOnly(false)]
        internal QAToolbar QAToolbar
        {
            get { return (QAToolbar)GetValue(QAToolbarProperty); }
            set { SetValue(QAToolbarProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonWindow.QAToolbar dependency property.
        /// </summary>
        internal static readonly DependencyProperty QAToolbarProperty =
            DependencyProperty.Register("QAToolbar", typeof(QAToolbar),
                                                        typeof(RibbonWindow),
                                                        new FrameworkPropertyMetadata((QAToolbar)null));

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.RibbonWindow.Text attached property for the 
        /// given dependency object.
        /// </summary>
        public static string GetText(DependencyObject obj)
        {
            return (string)obj.GetValue(TextProperty);
        }

        /// <summary>
        /// Sets the value of the UBCon.Ribbon.RibbonWindow.Text attached property for the 
        /// given dependency object.
        /// </summary>
        public static void SetText(DependencyObject obj, string value)
        {
            obj.SetValue(TextProperty, value);
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonWindow.Text attached property.
        /// </summary>
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.RegisterAttached("Text", typeof(string), typeof(RibbonWindow),
            new PropertyMetadata(null, new PropertyChangedCallback(OnTextChanged)));


        /// <summary>
        /// Gets the value which indicates the current state of UBCon.Ribbon.RibbonBar control.
        /// </summary>
        public RibbonBarMode Mode
        {
            get { return (RibbonBarMode)GetValue(ModeProperty); }
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonWindow.Mode dependency property.
        /// </summary>
        internal static readonly DependencyPropertyKey ModePropertyKey =
            DependencyProperty.RegisterReadOnly("Mode", typeof(RibbonBarMode), typeof(RibbonWindow),
            new PropertyMetadata(RibbonBarMode.ShowTabsAndCommands,
                new PropertyChangedCallback(OnModeChanged)));

        /// <summary>
        /// Gets or sets collection of controls which are visible in AutoHideMode.
        /// This is a dependency property.
        /// </summary>
        public ObservableCollection<UIElement> HiddenItems
        {
            get { return (ObservableCollection<UIElement>)GetValue(HiddenItemsProperty); }
            set { SetValue(HiddenItemsProperty, value); }
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonWindow.HiddenItems dependency property.
        /// </summary>
        public static readonly DependencyProperty HiddenItemsProperty =
            DependencyProperty.Register("HiddenItems", typeof(ObservableCollection<UIElement>), typeof(RibbonWindow));

        
        /// <summary>
        /// Identifies UBCon.Ribbon.RibbonWindow.Mode dependency property.
        /// </summary>
        internal static readonly DependencyProperty ModeProperty = ModePropertyKey.DependencyProperty;

        /// <summary>
        /// 
        /// </summary>
        internal RibbonBar InternalRibbonBar;

        /// <summary>
        /// 
        /// </summary>
        internal bool CanOpenAppMenu
        {
            get
            {
                return /*ContentDecorator != null*/
                    AppMenuPresenter != null &&
                    ApplicationMenu != null &&
                    ApplicationMenu.AppMenuSelectedContentPresenter != null;
            }
        }

        /// <summary>
        /// Gets or set storyboard animation for opening application menu. 
        /// </summary>
        internal Storyboard ShowAppMenuSB
        {
            get
            {
                if (showAppMenuSB == null)
                {
                    showAppMenuSB = new Storyboard();
                    DoubleAnimation da = new DoubleAnimation()
                    {
                        EasingFunction = new ExponentialEase()
                        {
                            EasingMode = EasingMode.EaseOut,
                            Exponent = 5
                        }
                    };

                    Storyboard.SetTarget(da, AppMenuPresenter);
                    Storyboard.SetTargetProperty(da, new PropertyPath(Constants.XPropertyPath));
                    da.From = -13.0D;
                    da.To = 0.0;
                    da.Duration = new Duration(TimeSpan.FromSeconds(0.35));
                    showAppMenuSB.Children.Add(da);
                    //showAppMenuSB = BuildAppMenuOpenStoryboard();
                }
                return showAppMenuSB;
            }
            set
            {
                showAppMenuSB = value;
            }
        }


        private bool IsValidRootPanel
        {
            get
            {
                return rootPanel != null;
            }
        }

        #endregion

        //------------------------------------------------------
        //
        //  Depenency Property Changed Callbacks
        //
        //------------------------------------------------------
        #region Depenency Property Changed Callbacks

        /// <summary>
        /// Coerces Theme property.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The object that the property exists on. When the callback is invoked, the property system will pass this value.</param>
        /// <param name="value">Type: System.Object. The new value of the property, prior to any coercion attempt.</param>
        /// <returns>Type: System.Object. The coerced value (with appropriate type). </returns>
        private static object CoerceTheme(DependencyObject sender, object value) 
        {
            return !NativeMethods.DwmIsCompositionEnabled() ? WindowTheme.Default : value;
        }

        /// <summary>
        /// Invoked when Theme property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnThemeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            RibbonWindow window = sender as RibbonWindow;
            WindowTheme newValue = (WindowTheme)e.NewValue;
            if (newValue == WindowTheme.Default)
            {
                window.HideButtons();
            }
            else if (newValue == WindowTheme.Classic) 
            {
                window.SetTitleBarMargin();

                window.EnableClassicStyle();
            }
        }

        /// <summary>
        /// Invoked when Mode property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnModeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            RibbonWindow window = sender as RibbonWindow;
            RibbonBarMode mode = (RibbonBarMode)e.NewValue;
            if (mode == RibbonBarMode.AutoHideMode)
            {
                //bool isCollapsable = true;
                window.SetValue(RibbonWindow.ResizeModeProperty, ResizeMode.NoResize);
                //foreach (UIElement ui in window.CaptionItems)
                //{
                //    isCollapsable = (bool)ui.GetValue(RibbonWindow.IsCollapsableProperty);
                //    if (isCollapsable)
                //    {
                //        ui.SetValue(UIElement.VisibilityProperty, Visibility.Collapsed);
                //    }
                //}
            }
            else
            {
                window.SetValue(RibbonWindow.ResizeModeProperty, ResizeMode.CanResize);
                //foreach (UIElement ui in window.CaptionItems)
                //{
                //    ui.SetValue(UIElement.VisibilityProperty, Visibility.Visible);
                //}
            }
        }

        /// <summary>
        /// Invoked when ResizeMode property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnResizeModeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { }

        /// <summary>
        /// Coerces ResizeMode property.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The object that the property exists on. When the callback is invoked, the property system will pass this value.</param>
        /// <param name="value">Type: System.Object. The new value of the property, prior to any coercion attempt.</param>
        /// <returns>Type: System.Object. The coerced value (with appropriate type). </returns>
        private static object CoerceResizeMode(DependencyObject sender, object value)
        {
            RibbonWindow rw = sender as RibbonWindow;
            if (rw.Mode == RibbonBarMode.AutoHideMode)
            {
                return ResizeMode.NoResize;
            }
            return value;
        }

        /// <summary>
        /// Invoked when WindowState property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnWindowStateChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { }

        /// <summary>
        /// Coerces WindowState property.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The object that the property exists on. When the callback is invoked, the property system will pass this value.</param>
        /// <param name="value">Type: System.Object. The new value of the property, prior to any coercion attempt.</param>
        /// <returns>Type: System.Object. The coerced value (with appropriate type). </returns>
        private static object CoerceWindowState(DependencyObject sender, object value)
        {
            RibbonWindow rw = sender as RibbonWindow;
            if (rw.Mode == RibbonBarMode.AutoHideMode)
            {
                return WindowState.Maximized;
            }
            return value;
        }


        /// <summary>
        /// Invoked when Text attached property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            RibbonWindow window = RibbonHelper.GetWindow(sender);
            if (window != null &&
                window.QAToolbar != null)
            {
                window.QAToolbar.OnTextChanged(sender as UIElement, (string)e.NewValue);
            }

        }

        /// <summary>
        /// Invoked when Title property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnTitleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            RibbonWindow window = sender as RibbonWindow;

            if (window.IsLoaded &&
                window.titleText != null)
            {
                window.fText = new FormattedText
                                    (
                                        window.Title,
                                        window.Dispatcher.Thread.CurrentCulture,
                                        System.Windows.FlowDirection.LeftToRight,
                                        new Typeface(window.titleText.FontFamily.ToString()),
                                        window.titleText.FontSize, window.titleText.Foreground
                                    );
            }
        }

        /// <summary>
        /// Invoked when EnableDefaulStyle attached property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnEnableDefaulStylePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            RibbonDropDownButton dButton = sender as RibbonDropDownButton;
            bool newValue = (bool)e.NewValue;

            if (dButton != null)
            {
                if (newValue)
                {
                    RibbonWindow window = RibbonHelper.GetWindow(dButton);

                    try
                    {
                        ComponentResourceKey key = new ComponentResourceKey()
                        {
                            TypeInTargetAssembly = typeof(SkinManagers.SkinManager),
                            ResourceId = "WindowOptionsButtonTemplate"
                        };
                        ControlTemplate value = RibbonHelper.GetResourceByKey<ControlTemplate>(key);

                        if (value != null)
                        {
                            dButton.SetValue(RibbonDropDownButton.TemplateProperty, value);
                        }
                    }

                    finally { }
                }
                else
                {
                    dButton.ClearValue(RibbonDropDownButton.TemplateProperty);
                }
            }
        }

        /// Invoked when ApplicationMenu property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnApplicationMenuPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ApplicationMenu newAppMenu = e.NewValue as ApplicationMenu, oldAppMenu = e.OldValue as ApplicationMenu;
            RibbonWindow window = sender as RibbonWindow;
            if (newAppMenu != null)
            {
                BindingOperations.SetBinding
                    (
                        newAppMenu,
                        ApplicationMenu.IsApplicationMenuOpenProperty,
                        new Binding("IsApplicationMenuOpen")
                        {
                            Source = window
                        }
                    );
            }
            if (oldAppMenu != null)
            {
                BindingOperations.ClearBinding(oldAppMenu, ApplicationMenu.IsApplicationMenuOpenProperty);
            }
        }

        /// <summary>
        /// Coerces IsApplicationMenuOpen property.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The object that the property exists on. When the callback is invoked, the property system will pass this value.</param>
        /// <param name="value">Type: System.Object. The new value of the property, prior to any coercion attempt.</param>
        /// <returns>Type: System.Object. The coerced value (with appropriate type). </returns>
        private static object CoerceIsApplicationMenuOpenProperty(DependencyObject d, object value)
        {
            RibbonWindow window = (RibbonWindow)d;
            if (window.ApplicationMenu != null && window.AppMenuPresenter!=null)
            {
                ApplicationMenu appMenu = window.ApplicationMenu;
                ContentPresenter menuPresenter = window.AppMenuPresenter;
                if (window.InternalRibbonBar != null && window.InternalRibbonBar._dropDownMenuPopup != null)
                {
                    if (appMenu.MenuStyle == ApplicationMenuStyle.Classic)
                    {
                        if (window.rootPanel.Children.Contains(menuPresenter))
                        {
                            window.rootPanel.Children.Remove(menuPresenter);
                            window.InternalRibbonBar.AddChildToMenuPopup(menuPresenter);
                            
                        }
                    }
                    else
                    {
                        if (!window.rootPanel.Children.Contains(menuPresenter))
                        {
                            window.InternalRibbonBar.RemoveChildFromMenuPopup();
                            window.rootPanel.Children.Add(menuPresenter);
                        }
                    }
                }
            }

            if (window.Width < 450)
            {
                window.Width = 450;
            }
            return value;
        }

        /// Invoked when IsApplicationMenuOpen property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnIsApplicationMenuOpenPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            bool newValue = (bool)e.NewValue;

            RibbonWindow window = d as RibbonWindow;
            if (window.InternalRibbonBar != null && window.InternalRibbonBar.Mode == RibbonBarMode.AutoHideMode)
            {
                window.shouldUpdatetitle = false;            
            }
            if (newValue)
            {
                if (window.InternalRibbonBar != null && window.InternalRibbonBar.Mode == RibbonBarMode.AutoHideMode) 
                {

                    if (window.InternalRibbonBar.ApplicationMenu == null || window.InternalRibbonBar.ApplicationMenu != null && window.InternalRibbonBar.ApplicationMenu.MenuStyle != ApplicationMenuStyle.Classic)
                    {
                        window.InternalRibbonBar.HideRibbonBar();
                    }
                    
                }
                window.TryOpenAppMenu();
            }
            else
            {
                window.TryCloseAppMenu();
            }
        }

        #endregion

        //------------------------------------------------------
        //
        //  Overrides
        //
        //------------------------------------------------------
        #region Overrieds

        /// <summary>
        /// Raises System.Windows.StateChanged event .
        /// </summary>
        protected override void OnStateChanged(EventArgs e)
        {
            base.OnStateChanged(e);
            SetTitleBarMargin();
        }

        /// <summary>
        /// Measures the size in layout required 
        /// for child elements and determines a size for the FrameworkElement-derived class.
        /// </summary>
        /// <param name="availableSize">The available size that this element can 
        /// give to child elements. Infinity can be specified as a value to indicate 
        /// that the element will size to whatever content is available.</param>
        /// <returns>The size that this element determines it needs during layout, based on 
        /// its calculations of child element sizes.</returns>
        protected override Size MeasureOverride(Size availableSize)
        {

            VerifyAccess();
            if (this.VisualChildrenCount > 0)
            {
                System.Windows.UIElement child = this.GetVisualChild(0) as System.Windows.UIElement;
                if (child != null)
                {

                    child.Measure(availableSize);
                    return child.DesiredSize;
                }
            }
            return base.MeasureOverride(availableSize);
        }

        /// <summary>
        /// Invalidates the measurement state (layout) for the element. (Inherited from UIElement.)
        /// </summary>
        /// <param name="availableSize">The available size that this element can give to child elements. 
        /// Infinity can be specified as a value to indicate that the element will size to whatever content is available.</param>
        /// <returns>The size that this element determines it needs during layout, based on its calculations of child element sizes.</returns>
        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            VerifyAccess();
            if (VisualChildrenCount > 0)
            {
                UIElement child = this.GetVisualChild(0) as UIElement;

                if (child != null)
                {
                    arrangeRect.Width = arrangeBounds.Width;
                    arrangeRect.Height = arrangeBounds.Height;

                    child.Arrange(arrangeRect);
                    UpdateTitleLocation(null);
                    if (Mode == RibbonBarMode.AutoHideMode)
                    {
                        if (!shouldUpdatetitle)
                        {
                            shouldUpdatetitle = true;
                        }
                    }
                    
                }
                return arrangeBounds;

            }
            return base.ArrangeOverride(arrangeBounds);
        }

        /// <summary>
        /// When overridden in a derived class, is invoked whenever application 
        /// code or internal processes call ApplyTemplate.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            mainBorder = GetTemplateChild(partOuterBorder) as FrameworkElement;
            titleText = GetTemplateChild(partTitleText) as TextBlock;
            //captionBorder = GetTemplateChild(CaptionBorderName) as FrameworkElement;

            if (icon != null)
            {
                icon.MouseLeftButtonDown -= IconMouseLeftButtonDown;
                icon.MouseRightButtonDown -= IconMouseRightButtonDown;

            }

            icon = GetTemplateChild(PART_IconName) as Image;

            if (icon != null)
            {
                icon.MouseLeftButtonDown += new MouseButtonEventHandler(IconMouseLeftButtonDown);
                icon.MouseRightButtonDown += new MouseButtonEventHandler(IconMouseRightButtonDown);

            }

            cButPanel = GetTemplateChild(PART_CaptionButtonsHolderName) as StackPanel;

            hiddenItemsPanel = GetTemplateChild(PART_HiddenItemsPanelName) as StackPanel;

            AppMenuPresenter = GetTemplateChild(AppMenuPresenterName) as ContentPresenter;

            if (AppMenuPresenter != null)
            {
                AppMenuPresenter.RenderTransform = new TranslateTransform();
            }

            ContextualHeaderPanel = GetTemplateChild(contextualHeaderPanelName) as Canvas;

            rootPanel = GetTemplateChild(rootPanelName) as Grid;

            QAToolbarPresenter = GetTemplateChild(QAToolbarHostName) as ContentPresenter;

            _titleLocator = GetTemplateChild(PART_TitleLocatorName) as FrameworkElement;

            if (_titleLocator == null)
            {
                throw new NullReferenceException("title locator cannot be null. TemplatePart name: PART_TitleLocator");
            }
            if (showHiddenBar != null)
            {
                showHiddenBar.Click -= ShowHiddenBar;
            }

            showHiddenBar = GetTemplateChild(PART_HideButtonName) as Button;

            if (showHiddenBar != null)
            {
                showHiddenBar.Click += ShowHiddenBar;
            }
        }

      

        /// <summary>
        /// Raises the System.Windows.FrameworkElement.Initialized event. 
        /// This method is invoked whenever System.Windows.FrameworkElement.IsInitialized is set to true internally.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInitialized(EventArgs e)
        {
            foreach (UIElement item in QAToolbarItems)
            {
                string itemText = (string)item.GetValue(RibbonWindow.TextProperty);
                if (!string.IsNullOrEmpty(itemText))
                {
                    QAToolbar.OnTextChanged(item, itemText);
                }
            }

            base.OnInitialized(e);
        }
       
        #endregion

        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
        #region Private Methods

        /// <summary>
        /// Set title bar's margin window theme is changed to Classic.
        /// </summary>
        private void SetTitleBarMargin()
        {
            titleBarMargin.Top = -System.Windows.SystemParameters.CaptionHeight - _resizeFrameBorderSize / 2;
            if (WindowState == WindowState.Maximized)
            {
                titleBarMargin.Top = -System.Windows.SystemParameters.CaptionHeight - 1;
            }
            SetValue(TitleBarMarginProperty, titleBarMargin);
        }

        /// <summary>
        /// Initializes QAToolbar control.
        /// </summary>
        private void InitializeQAToolbar()
        {
            QAToolbar = new QAToolbar();
            QAToolbar.RibbonWindow = this;
        }

        private void EnsureContextualHeadersProperlyLocated(FrameworkElement relativeTo)
        {
            double x = 0;
            if (cButPanel != null && InternalRibbonBar != null)
            {
                RibbonBar bar = InternalRibbonBar;
                Point p1 = cButPanel.TranslatePoint(emptyPoint, relativeTo);

                for (int i = 0; i < bar.ContextualItems.Count; i++)
                {
                    ContextualTabItemsGroup group = bar.ContextualItems[i];

                    if (group.Visibility == System.Windows.Visibility.Visible &&
                        group.Header != null)
                    {

                        x = Canvas.GetLeft(group.Header);
                        if (x + group.Header.Width + 5 >= p1.X)
                        {
                            group.Header.IsActive = false;

                        }
                        else
                        {
                            group.Header.IsActive = true;
                        }

                    }
                }
            }

        }



        /// <summary>
        /// Resets caption text when any contextual item(s) is (are) visible.
        /// </summary>
        internal void UpdateTitleLocation(FrameworkElement relativeTo)
        {
            updatingTitleLocation = true;

            EnsureContextualHeadersProperlyLocated(relativeTo);
            double space = _titleLocator.RenderSize.Width, width = 0;
           
            if (Theme == WindowTheme.Classic)
            {
                space -= 3 * System.Windows.SystemParameters.WindowCaptionButtonWidth;
            }
           
            if (fText == null)
            {
                fText = new FormattedText
                    (
                        Title,
                        Dispatcher.Thread.CurrentCulture,
                        System.Windows.FlowDirection.LeftToRight,
                        new Typeface(titleText.FontFamily.ToString()),
                        titleText.FontSize, titleText.Foreground
                    );
            }
            if (titleText != null && InternalRibbonBar != null && shouldUpdatetitle)
            {
                double beginX = _titleLocator.TranslatePoint(emptyPoint, relativeTo).X, endX = beginX + space,
                       beginPoint = 0, endPoint = 0;

                if (InternalRibbonBar.ContextualItemsOpen)
                {
                    InternalRibbonBar.GetContextualLocations(ref beginPoint, ref endPoint);
                    LeftSpace = Math.Min(beginPoint - beginX, space);
                    RightSpace = Math.Min(endX - endPoint, space);

                    if ((LeftSpace > RightSpace && LeftSpace <= titleMinSize) ||
                        (LeftSpace <= RightSpace && RightSpace <= titleMinSize))
                    {
                        if (QAToolbar != null && QAToolbar.IsAboveRibbon == true)
                        {
                            while (LeftSpace <= titleMinSize && QAToolbar.HasValidItems)
                            {
                                width = QAToolbar.GetLastValidItemWidth();
                                LeftSpace += width;
                                beginX -= width;
                                QAToolbar.InsertNextToHiddenPanel();
                            }
                        }
                        space = Math.Min(fText.Width, LeftSpace);
                        if (space <= 0)
                        {
                            space = 1.0D;
                        }
                        titleText.SetValue(TextBlock.WidthProperty, space);
                        if (LeftSpace > space)
                        {
                            beginX += (LeftSpace - space) / 2;
                        }
                    }
                    else if (LeftSpace > RightSpace && LeftSpace > titleMinSize)
                    {
                        if (QAToolbar != null && QAToolbar.IsAboveRibbon == true)
                        {
                            width = QAToolbar.GetLastHiddenItemWidth();

                            while (LeftSpace - width > titleMinSize && QAToolbar.HasRemovedItems)
                            {
                                LeftSpace -= width;
                                beginX += width;
                                QAToolbar.RemoveNextFromHiddenPanel();
                                width = QAToolbar.GetLastHiddenItemWidth();
                            }
                        }
                        space = Math.Min(space, fText.Width);
                        if (LeftSpace > space)
                        {
                            beginX += (LeftSpace - space) / 2;
                        }
                        titleText.SetValue(TextBlock.WidthProperty, space);
                    }
                    else if (LeftSpace <= RightSpace && RightSpace > titleMinSize)
                    {
                        space = Math.Min(fText.Width, RightSpace);
                        if (space <= 0)
                        {
                            space = 1.0D;
                        }
                        titleText.SetValue(TextBlock.WidthProperty, space);

                        beginX = endPoint;

                        if (RightSpace > space)
                        {
                            beginX += (RightSpace - space) / 2;
                        }

                        if (LeftSpace > 0)
                        {
                            if (QAToolbar != null && QAToolbar.IsAboveRibbon == true)
                            {
                                width = QAToolbar.GetLastHiddenItemWidth();

                                while (LeftSpace - width > 0 && QAToolbar.HasRemovedItems)
                                {
                                    LeftSpace -= width;
                                    QAToolbar.RemoveNextFromHiddenPanel();
                                    width = QAToolbar.GetLastHiddenItemWidth();
                                }
                            }
                        }
                    }

                    Canvas.SetLeft(titleText, beginX);
                }
                else
                {
                    UpdateQAToolbar(space, relativeTo);
                }
            }
            else if (titleText != null && InternalRibbonBar == null)
            {
                UpdateQAToolbar(space, relativeTo);
            }
            if (QAToolbar != null && QAToolbar.IsAboveRibbon == false)
            {
                QAToolbar.Measure(infineSize);
                space = RenderSize.Width - QAToolbar.DesiredSize.Width;
                if (space < 0)
                {
                    do
                    {
                        width = QAToolbar.GetLastValidItemWidth();
                        space += width;
                        QAToolbar.InsertNextToHiddenPanel();
                    }
                    while (space < 0 && QAToolbar.HasValidItems);
                }
                else
                {
                    width = QAToolbar.GetLastHiddenItemWidth();
                    while (space - width >= 0 && QAToolbar.HasRemovedItems)
                    {
                        space -= width;
                        QAToolbar.RemoveNextFromHiddenPanel();
                        width = QAToolbar.GetLastHiddenItemWidth();
                    }
                }
            }
            double difference = 0;
            //Contextual tab items may overlap with quick access toolbar. 
            //In this case we hide some QAToolbar items.
            if (IsQAOverlappedWithContextual(out difference))
            {
                while (difference > 0 && QAToolbar.HasValidItems)
                {
                    width = QAToolbar.GetLastValidItemWidth();
                    difference -= width;
                    QAToolbar.InsertNextToHiddenPanel();
                }
            }
            updatingTitleLocation = false;
            
        }

        /// <summary>
        /// Gets a boolean value that indicates whether QAToolBar is 
        /// overlapped with visible contextual tab item.
        /// </summary>
        /// <returns>true if is overlapped false otherwise</returns>
        private bool IsQAOverlappedWithContextual(out double  difference) 
        {
            difference = 0;
            if (QAToolbar != null && QAToolbar.IsAboveRibbon==true&& InternalRibbonBar != null)
            {
                int count = InternalRibbonBar.ContextualItems.Count;
                double x1 = 0, x2 = QAToolbar.TranslatePoint(emptyPoint, null).X + QAToolbar.RenderSize.Width;
                for (int i = 0; i < count; i++)
                {
                    ContextualTabItemsGroup group = InternalRibbonBar.ContextualItems[i];
                    if (group.Visibility == System.Windows.Visibility.Visible &&
                      group.Header != null)
                    {
                        x1 = Canvas.GetLeft(group.Header);
                        difference = x2 - x1;
                        if (difference > 0) 
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// Updates QAToolbar and Title text according to specified avaliable space.
        /// </summary>
        private void UpdateQAToolbar(double space, FrameworkElement relativeTo)
        {
            double beginX = _titleLocator.TranslatePoint(emptyPoint, relativeTo).X, endX = beginX + space, width = 0;
            double neededSpace = Math.Min(fText.Width, space);

            if (neededSpace > titleMinSize)
            {
                if (QAToolbar != null&&QAToolbar.IsAboveRibbon==true)
                {
                    width = QAToolbar.GetLastHiddenItemWidth();

                    while (space - width > titleMinSize && QAToolbar.HasRemovedItems)
                    {
                        space -= width;
                        beginX += width;
                        QAToolbar.RemoveNextFromHiddenPanel();
                        width = QAToolbar.GetLastHiddenItemWidth();

                    }
                }

                titleText.SetValue(TextBlock.WidthProperty, Math.Min(neededSpace, space));
                if (space > neededSpace)
                {
                    neededSpace = (space - neededSpace) / 2;
                    beginX += neededSpace;
                }
                
            }
            else
            {
                width = 0;

                if (QAToolbar != null && QAToolbar.IsAboveRibbon == true)
                {
                    space = RenderSize.Width - beginX - (cButPanel != null ? cButPanel.DesiredSize.Width : 3 * System.Windows.SystemParameters.WindowCaptionButtonWidth);
                    do
                    {
                        width = QAToolbar.GetLastValidItemWidth();
                        space += width;
                        beginX -= width;
                        QAToolbar.InsertNextToHiddenPanel();

                    }
                    while (space <= titleMinSize && QAToolbar.HasValidItems);
                }
                width = space;
                space = Math.Min(fText.Width, space);
                if (width > space)
                {
                    beginX += (width - space) / 2;
                }
                if (space <= 0)
                {
                    space = 1.0D;
                }
                titleText.SetValue(TextBlock.WidthProperty, space);
            }

            Canvas.SetLeft(titleText, beginX);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="parameter"></param>
        private void OnOpenCloseApplicationMenuCommandExecuted(object parameter)
        {
            if (parameter != null)
            {
                string convertBool = parameter.ToString();
                if (convertBool == Constants.True || convertBool == Constants.False)
                {
                    SetValue(IsApplicationMenuOpenProperty, bool.Parse(convertBool));
                }
            }
        }

        internal void TryOpenAppMenu()
        {
            if (CanOpenAppMenu && ApplicationMenu.MenuStyle == ApplicationMenuStyle.Default)
            {
                ApplicationMenu.AppMenuSelectedContentPresenter.Opacity = 1.0D;
                TranslateTransform translate = AppMenuPresenter.RenderTransform as TranslateTransform;
                translate.X = -13.0D;

                if (perfomaceHelper.CanAnimate &&
                    ShowAppMenuSB != null && ApplicationMenu.AnimatedOpen)
                {
                    ShowAppMenuSB.Begin();
                }
                else
                {
                    translate.X = 0.0D;
                }
            }
        }

        private void TryCloseAppMenu()
        {
            if (CanOpenAppMenu && ApplicationMenu.MenuStyle == ApplicationMenuStyle.Default)
            {
                //ApplicationMenu.AppMenuSelectedContentPresenter.Opacity = 0.0D;
                ApplicationMenu.AppMenuSelectedContentPresenter.SetValue(ContentPresenter.OpacityProperty, 0.0D);

                (AppMenuPresenter.RenderTransform as TranslateTransform).X = -95.0D;

                ApplicationMenu.AppMenuSelectedContentPresenter.SetValue(ContentPresenter.OpacityProperty, 1.0D);
                //ApplicationMenu.AppMenuSelectedContentPresenter.Opacity = 1.0D;
                //OnApplicationMenuClosed();
                
            }
        }

        private bool shouldUpdatetitle = true;
        /// <summary>
        /// Sets low-level window procedure.
        /// </summary>
        private void SetHook()
        {
            EventHandler handler = null;

            handler = delegate(object sender, EventArgs e)
            {
                base.SourceInitialized -= handler;

                handler = null;
                
                HwndSource source = (HwndSource)PresentationSource.FromVisual(this);
                _hwnd = source.Handle;
                NativeMethods.RECT _clientRect, _windowRect;
                NativeMethods.GetWindowRect(_hwnd, out _windowRect);
                NativeMethods.GetClientRect(_hwnd, out _clientRect);
                _resizeFrameBorderSize = (_windowRect.Width - _clientRect.Width) / 2;

                titleBarMargin = new Thickness()
                {
                    Left = 0,
                    Top = -System.Windows.SystemParameters.CaptionHeight - _resizeFrameBorderSize / 2,
                    Right = 0,
                    Bottom = 0
                };

                SetValue(TitleBarMarginProperty, titleBarMargin);

                SetValue(WindowResizeFrameProperty,
                        new Thickness()
                        {
                            Left = _resizeFrameBorderSize,
                            Top = System.Windows.SystemParameters.CaptionHeight + (int)_resizeFrameBorderSize,
                            Right = _resizeFrameBorderSize,
                            Bottom = _resizeFrameBorderSize
                        }
                    );
               
                if (Theme == WindowTheme.Default)
                {
                    this.HideButtons();
                }

                
                source.AddHook(new HwndSourceHook(WndProc));
            };
            base.SourceInitialized += handler;
        }

        [SecurityCritical, 
        SecuritySafeCritical]
        private void WndProcHitTest(IntPtr hwnd, IntPtr lParam, ref bool handled, ref IntPtr result)
        {
            int xy = lParam.ToInt32();
            Point point = new Point(NativeMethods.SignedLoWord(xy), NativeMethods.SignedHiWord(xy));
           
            NativeMethods.RECT rect = new NativeMethods.RECT();
            NativeMethods.GetWindowRect(hwnd, out rect);
            Rect wndRect = new Rect(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
            NativeMethods.HT ht = NCHITTEST(point, wndRect);
           
            result = new System.IntPtr((int)ht);
            handled = ht != NativeMethods.HT.NOWHERE;
        }

        [SecurityCritical, SecuritySafeCritical]
        private NativeMethods.HT NCHITTEST(Point point, Rect wndRect)
        {
            double  borderSize = System.Windows.SystemParameters.ResizeFrameVerticalBorderWidth, 
                    titleHeight = System.Windows.SystemParameters.CaptionHeight;

            if (point.Y < wndRect.Top + borderSize)
            {
                if (point.X < wndRect.Left + borderSize) return NativeMethods.HT.TOPLEFT;
                if (point.X > wndRect.Right - borderSize) return NativeMethods.HT.TOPRIGHT;
                return NativeMethods.HT.TOP;
            }
            if (point.Y > wndRect.Bottom - borderSize)
            {
                if (point.X < wndRect.Left + borderSize) return NativeMethods.HT.BOTTOMLEFT;
                if (point.X > wndRect.Right - borderSize) return NativeMethods.HT.BOTTOMRIGHT;
                return NativeMethods.HT.BOTTOM;
            }
            if (point.X < wndRect.Left+borderSize)
            {
                return NativeMethods.HT.LEFT;
            }
            if (point.X > wndRect.Right - borderSize) return NativeMethods.HT.RIGHT;
            if (point.Y < wndRect.Top + titleHeight)
            {
                Point localPoint = ScreenToLocal(point);
                IInputElement e = InputHitTest(localPoint);

                if (e == null)
                {
                    return NativeMethods.HT.CAPTION;
                }
                else
                {
                    if (e == mainBorder || e == _titleLocator)
                    {
                        return NativeMethods.HT.CAPTION;
                    }

                    UIElement ue = e as UIElement;

                    if (ue == null ||
                            !ue.IsHitTestVisible ||
                                ue == titleText || (ue as FrameworkElement).TemplatedParent is ContextualTabItemsGroup)
                    {
                        return NativeMethods.HT.CAPTION;
                    }
                }
            }
            return NativeMethods.HT.NOWHERE;
        }

        [SecurityCritical, 
        SecuritySafeCritical]
        private Point ScreenToLocal(Point point)
        {
            NativeMethods.RECT rect;
            NativeMethods.GetWindowRect(new System.Windows.Interop.WindowInteropHelper(this).Handle, out rect);
            Matrix matrix = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
            point.Offset((double)(-1 * rect.Left), (double)(-1 * rect.Top));
            point.X *= matrix.M11;
            point.Y *= matrix.M22;
            return point;
        }

        private void RegisterCommands()
        {
            Type ownerType = typeof(RibbonWindow);

            CommandBindings.Add(new CommandBinding(MinimizeCommand, new ExecutedRoutedEventHandler(PerformMinimize)));

            CommandBindings.Add(new CommandBinding(MaximizeCommand, new ExecutedRoutedEventHandler(PerformMaximize)));

            CommandBindings.Add(new CommandBinding(CloseCommand, new ExecutedRoutedEventHandler(PerformClose)));

            CommandManager.RegisterClassCommandBinding(ownerType, new CommandBinding(SystemCommands.ShowSystemMenuCommand, SystemMenuExecuted, SystemMenuCanExecute));
        }

        #endregion

        //------------------------------------------------------
        //
        //  Event Handlers
        //
        //------------------------------------------------------
        #region Event Handlers

        /// <summary>
        /// Invoked when (PART_HideButton) button is pressed.
        /// </summary>
        private void ShowHiddenBar(object sender, RoutedEventArgs e)
        {
            if (InternalRibbonBar != null)
            {
                InternalRibbonBar.ShowHiddenBar();
            }
        }

        /// <summary>
        /// Occurs when the element is laid out, rendered, and ready for interaction. 
        /// (Inherited from FrameworkElement.)
        /// </summary>
        /// <param name="sender">Owner of the event.</param>
        /// <param name="e">Event data for the event.</param>
        private void OnWindowLoaded(object sender, RoutedEventArgs e)
        {
            //int t = NativeMethods.GetSystemMetrics(30);
            //Console.WriteLine(t);
            Loaded -= OnWindowLoaded;
            if (cButPanel != null)
            {
                foreach (UIElement item in CaptionItems)
                {
                    cButPanel.Children.Insert(0, item);
                }
            }

            if (hiddenItemsPanel != null) 
            {
                foreach (UIElement item in HiddenItems)
                {
                    hiddenItemsPanel.Children.Insert(0, item);
                }
            }

            if (rootPanel != null)
            {

                if (SkinManagers.SkinManager.OfficeBlueTheme != null)
                {
                    ComponentResourceKey key = new ComponentResourceKey(typeof(RibbonWindow), "Office2007AppMenuButton");
                    ToggleButton toggleButton = RibbonHelper.GetResourceByKey<ToggleButton>(key);
                    if (toggleButton != null)
                    {
                        rootPanel.Children.Add(toggleButton);
                    }
                }

            }
           
        }

        /// <summary>
        /// Occurs when the left mouse button is pressed while the mouse pointer is over this element.
        /// </summary>
        /// <param name="sender">Object that send the event.</param>
        /// <param name="e">Event arguments for the routed event that is raised by UIElement.</param>
        private void IconMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;

            if (e.ClickCount == 1)
            {
                if (SystemCommands.ShowSystemMenuCommand.CanExecute(null, this))
                {
                    SystemCommands.ShowSystemMenuCommand.Execute(null, this);
                }
            }
            else if (e.ClickCount == 2)
            {
                if (ApplicationCommands.Close.CanExecute(null, this))
                {
                    ApplicationCommands.Close.Execute(null, this);
                }
            }

            
        }

        /// <summary>
        /// Occurs when the right mouse button is pressed while the mouse pointer is over this element.
        /// </summary>
        /// <param name="sender">Object that send the event.</param>
        /// <param name="e">Event arguments for the routed event that is raised by UIElement.</param>
        private void IconMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (SystemCommands.ShowSystemMenuCommand.CanExecute(e, this))
            {
                SystemCommands.ShowSystemMenuCommand.Execute(e, this);
            }
        }

        /// <summary>
        /// Invoked when item is added, removed, changed, moved, or the entire collection is refreshed.
        /// </summary>
        private void OnCaptionItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (IsLoaded && cButPanel != null)
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        foreach (UIElement ui in e.NewItems)
                        {
                            cButPanel.Children.Insert(0, ui);
                        }
                        break;

                    case NotifyCollectionChangedAction.Remove:

                        foreach (UIElement ui in e.OldItems)
                        {
                            cButPanel.Children.Remove(ui);
                        }
                        break;
                }
            }
        }

        /// <summary>
        /// Invoked when item is added, removed, changed, moved, or the entire collection is refreshed.
        /// </summary>
        private void OnHiddenItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
        {
            if (IsLoaded && hiddenItemsPanel != null)
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        foreach (UIElement ui in e.NewItems)
                        {
                            hiddenItemsPanel.Children.Insert(0, ui);
                        }
                        break;

                    case NotifyCollectionChangedAction.Remove:

                        foreach (UIElement ui in e.OldItems)
                        {
                            hiddenItemsPanel.Children.Remove(ui);
                        }
                        break;
                }
            }
        }

        /// <summary>
        /// Invoked when item is added, removed, changed, moved, or the entire collection is refreshed.
        /// </summary>
        private void OnQAToolbarItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (QAToolbarItems.Count > 0)
            {
                if (QAToolbar == null)
                {
                    InitializeQAToolbar();
                }
                else if (QAToolbar.Visibility == System.Windows.Visibility.Collapsed)
                {
                    QAToolbar.Visibility = System.Windows.Visibility.Visible;

                }
            }
            else if (QAToolbarItems.Count == 0 && QAToolbar != null)
            {
                QAToolbar.Visibility = System.Windows.Visibility.Collapsed;
            }

            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    foreach (UIElement item in e.NewItems)
                    {
                        QAToolbar.AddChild(item);
                    }
                    break;

                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:

                    break;
            }
        }

        internal void SetWindowRgn() 
        {
            NativeMethods.RECT rect;
            IntPtr hwnd = new WindowInteropHelper(this).Handle;
            NativeMethods.GetWindowRect(hwnd, out rect);
            int w = rect.Width + 1;
            int h = rect.Height + 1;
            IntPtr rgn = NativeMethods.CreateRectRgn(0, 0, w, h);
            NativeMethods.SetWindowRgn(hwnd, rgn, NativeMethods.IsWindowVisible(hwnd));
        }

        /// <summary>
        /// Invoked when window's size changes.
        /// </summary>
        /// <param name="sender">Owner of the event.</param>
        /// <param name="e">Event data for the event.</param>
        private void OnWindowSizeChanged(object sender, SizeChangedEventArgs e)
        {

          //  SetWindowRgn();

            if (IsApplicationMenuOpen)
            {
                MinWidth = 450;
            }

            if (QAToolbar != null)
            {
                if (e.WidthChanged)
                {
                    if (InternalRibbonBar != null)
                    {
                        RibbonBar bar = InternalRibbonBar;

                        if (e.NewSize.Width <= 183)
                        {
                            if (bar.Visibility == System.Windows.Visibility.Visible)
                            {
                                bar.Visibility = Visibility.Collapsed;
                                MinWidth = 183;
                            }
                        }
                        else
                        {
                            if (bar.Visibility == Visibility.Collapsed)
                            {
                                bar.Visibility = Visibility.Visible;
                            }
                        }

                    }

                }
                else if (e.HeightChanged)
                {

                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender">Owner of the event.</param>
        /// <param name="args">Event data of the event.</param>
        private static void SystemMenuCanExecute(object sender, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = true;
        }

        /// <summary>
        /// Occurs when right mouse button is pressed on icon image to show default system menu.
        /// </summary>
        /// <param name="sender">Owner of the event.</param>
        /// <param name="args">Event data of the event which provides System.Windows.Input.CommandManager.Executed
        /// and System.Windows.Input.CommandManager.PreviewExecuted routed events.</param>
        private static void SystemMenuExecuted(object sender, ExecutedRoutedEventArgs args)
        {
            RibbonWindow rw = sender as RibbonWindow;

            if (rw != null)
            {
                // For right-clicks, display the system menu from the point of the mouse click.
                // For left-clicks, display the system menu in the top-left corner of the client area.
                Point devicePoint;
                MouseButtonEventArgs e = args.Parameter as MouseButtonEventArgs;
                if (e != null)
                {
                    // This is the right-click handler.  The presence of a MouseButtonEventArgs as args.Parameter
                    // indicates we are handling right-click.
                    devicePoint = rw.PointToScreen(e.GetPosition(rw));
                }
                else if (rw.mainBorder != null)
                {
                    // This is the left-click handler.  We can only handle it correctly if the _clientAreaBorder
                    // template part is defined, because that is where we want to position the system menu.
                    devicePoint = rw.mainBorder.PointToScreen(rw.emptyPoint);
                }
                else
                {
                    // We can't handle this correctly, so exit.
                    return;
                }

                CompositionTarget compositionTarget = PresentationSource.FromVisual(rw).CompositionTarget;
                SystemCommands.ShowSystemMenu(rw, compositionTarget.TransformFromDevice.Transform(devicePoint));
                args.Handled = true;
            }
        }

        /// <summary>
        /// Window procedure WndProc
        /// </summary>
        [SecurityCritical,
         SecuritySafeCritical]
        protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            IntPtr result = IntPtr.Zero;

            NativeMethods.WindowMessages wm = (NativeMethods.WindowMessages)msg;

            if (Environment.OSVersion.Version.Major >= 6)
            {
                handled = NativeMethods.DwmDefWindowProc(hwnd, msg, wParam, lParam, out result);
            }

            if (!handled)
            {
                switch (wm)
                {
                    case NativeMethods.WindowMessages.WM_GETMINMAXINFO:

                        if (Theme == WindowTheme.Default)
                        {
                            WmGetMinMaxInfo(hwnd, lParam);

                            handled = true;
                        }
                        break;

                    case NativeMethods.WindowMessages.WM_NCCALCSIZE:
                        handled = true;
                        result = IntPtr.Zero;
                        break;

                    case NativeMethods.WindowMessages.WM_SIZE:
                        handled = false;
                        break;

                    case NativeMethods.WindowMessages.WM_SETICON:
                        handled = true;
                        return IntPtr.Zero;

                    case NativeMethods.WindowMessages.WM_SETTEXT:
                        handled = true;
                        break;

                    case NativeMethods.WindowMessages.WM_NCLBUTTONDOWN:

                        if (Theme== WindowTheme.Default && 
                            WindowState == System.Windows.WindowState.Normal&&
                            ResizeMode== System.Windows.ResizeMode.CanResize)
                        {
                            SetMouseCursorAndResize(hwnd, lParam, true);
                        }
                        break;

                    case NativeMethods.WindowMessages.WM_NCMOUSEMOVE:
                        //
                        if (Theme == WindowTheme.Default &&
                            WindowState == System.Windows.WindowState.Normal &&
                            ResizeMode == System.Windows.ResizeMode.CanResize)
                        {
                            SetMouseCursorAndResize(hwnd, lParam, false);
                        }
                        
                        break;

                    case NativeMethods.WindowMessages.WM_NCHITTEST:
                        if (result == System.IntPtr.Zero)
                        {
                            WndProcHitTest(hwnd, lParam, ref handled, ref result);
                            ncHitResult = (NativeMethods.HT)result;
                        }
                        break;

                    case NativeMethods.WindowMessages.WM_DWMCOMPOSITIONCHANGED:
                        
                        //because classic window can be enabled only when DWM is enabled,
                        //we have to ensure that a Theme value is valid.
                        CoerceValue(ThemeProperty);

                        //From MSDN:
                        //"If an application processes this message, it should return zero."
                        result = System.IntPtr.Zero;
                        break;
                }
               
            }

            return result;
        }

        private void SetMouseCursorAndResize(IntPtr hWnd, IntPtr lParam, bool shouldResize) 
        {
            
            int val = -1;
            switch (ncHitResult)
            {
                case NativeMethods.HT.LEFT:
                    val = 1;
                    Mouse.SetCursor(Cursors.SizeWE);
                break;

                case NativeMethods.HT.RIGHT:
                    val = 2;
                    Mouse.SetCursor(Cursors.SizeWE);
                 break;

                case NativeMethods.HT.TOP:
                 val = 3;
                 Mouse.SetCursor(Cursors.SizeNS);
                break;

                case NativeMethods.HT.BOTTOM:
                 val = 6;
                 Mouse.SetCursor(Cursors.SizeNS);
                break;

                case NativeMethods.HT.TOPLEFT:
                 val = 4;
                 Mouse.SetCursor(Cursors.SizeNWSE);
                break;

                case NativeMethods.HT.TOPRIGHT:
                 val = 5;
                 Mouse.SetCursor(Cursors.SizeNESW);
                break;

                case NativeMethods.HT.BOTTOMLEFT:
                 val = 7;
                 Mouse.SetCursor(Cursors.SizeNESW);
                break;

                case NativeMethods.HT.BOTTOMRIGHT:
                 val = 8;
                 Mouse.SetCursor(Cursors.SizeNWSE);
                break;
            }
            if (val > -1 && shouldResize) 
            {
                NativeMethods.DefWindowProc(hWnd, NativeMethods.WindowMessages.WM_SYSCOMMAND,  new IntPtr((int)NativeMethods.SystemCommands.SC_SIZE + val), lParam); 
            }
        }

        private void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
        {

            NativeMethods.MINMAXINFO mmi = (NativeMethods.MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(NativeMethods.MINMAXINFO));

            // Adjust the maximized size and position to fit the work area of the correct monitor
            IntPtr monitor = NativeMethods.MonitorFromWindow(hwnd, (int)NativeMethods.HT.MONITOR_DEFAULTTONEAREST);

            if (monitor != System.IntPtr.Zero)
            {

                NativeMethods.MONITORINFO monitorInfo = new NativeMethods.MONITORINFO();
                NativeMethods.GetMonitorInfo(monitor, monitorInfo);
                NativeMethods.RECT rcWorkArea = monitorInfo.rcWork;
                NativeMethods.RECT rcMonitorArea = monitorInfo.rcMonitor;
                mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.Left - rcMonitorArea.Left);
                mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.Top - rcMonitorArea.Top);
                mmi.ptMaxSize.x = Math.Abs(rcWorkArea.Right - rcWorkArea.Left);
                mmi.ptMaxSize.y = Math.Abs(rcWorkArea.Bottom - rcWorkArea.Top);
            }

            Marshal.StructureToPtr(mmi, lParam, true);
        }

        /// <summary>
        /// Calculates avaliable left space relative to visible UBCon.Ribbon.ContextualTabItemsGroup controls.
        /// </summary>
        internal void SetLeftSpace(double absXpos)
        {
            LeftSpace = 0;
            
            if (QAToolbar != null)
            {
                LeftSpace = absXpos - QAToolbar.TranslatePoint(emptyPoint, this).X - QAToolbar.ActualWidth;
            }
            else
            {
                if (icon != null)
                {
                    LeftSpace = absXpos - icon.TranslatePoint(emptyPoint, this).X - icon.ActualWidth;
                }
            }

        }

        /// <summary>
        /// Calculates avaliable right space relative to visible UBCon.Ribbon.ContextualTabItemsGroup controls.
        /// </summary>
        internal void SetRightSpace(double absXpos)
        {
            RightSpace = 0;

            if (cButPanel != null)
            {
                RightSpace = Width - absXpos - cButPanel.ActualWidth;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="header"></param>
        internal void AddContextualHeader(ContextualItemsHeader header)
        {
            if (ContextualHeaderPanel != null)
            {
                ContextualHeaderPanel.Children.Add(header);
            }
        }

        /// <summary>
        /// Removes the specified header control from the panel which holds this item.
        /// </summary>
        internal void RemoveContuxtualHeader(ContextualItemsHeader header)
        {
            if (ContextualHeaderPanel != null)
            {
                ContextualHeaderPanel.Children.Remove(header);
            }
        }


        #endregion

        //------------------------------------------------------
        //
        //  Fields
        //
        //------------------------------------------------------
        #region Fields
        private const string partOuterBorder = "PART_OuterBorder",
                             partTitleText = "PART_TitleText",
                             PART_IconName = "PART_Icon",
                             QAToolbarHostName = "PART_QAToolbarHost",
                             AppMenuPresenterName = "PART_AppMenuPresenter",
                             contextualHeaderPanelName = "PART_ContextualHeaderPanel",
                             footerContentPresenterName = "PART_Footer",
                             PART_TitleLocatorName = "PART_TitleLocator",
                             rootPanelName = "PART_RootPanel",
                             PART_CaptionButtonsHolderName = "PART_CaptionButtonsHolder",
                             PART_HideButtonName = "PART_HideButton",
                             PART_HiddenItemsPanelName = "PART_HiddenItemsPanel";

        private FrameworkElement mainBorder, _titleLocator;//, captionBorder;
        private TextBlock titleText;
        internal Image icon;
        internal StackPanel cButPanel, hiddenItemsPanel;
        private ContentPresenter AppMenuPresenter;
        internal ContentPresenter QAToolbarPresenter;
        //private AdornerDecorator ContentDecorator { get; set; }
        internal bool updatingTitleLocation = false;
        internal Canvas ContextualHeaderPanel;
        private Point emptyPoint = new Point(0, 0);
        private ApplicationPerfomanceHelper perfomaceHelper = new ApplicationPerfomanceHelper();
        private double LeftSpace = 0, RightSpace = 0;
        private FormattedText fText = null;
        internal Button showHiddenBar;
        
        private Rect arrangeRect = new Rect() 
        { 
            X = 0, 
            Y = 0 
        };
        private Size infineSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
        private Storyboard showAppMenuSB;
        internal Grid rootPanel;
        private const double titleMinSize = 35.0D;
        private NativeMethods.HT ncHitResult;
        internal double _resizeFrameBorderSize = 4.0D;
        private Thickness titleBarMargin;
        private IntPtr _hwnd;
        #endregion

        //------------------------------------------------------
        //
        //  IRibbonControl Implementation
        //
        //------------------------------------------------------
        #region IRibbonControl Implementation

        /// <summary>
        /// Gets a boolean value indicating whether the contol's size is large
        /// </summary>
        public bool IsLarge
        {
            get { return true; }
        }

        #endregion
    }
}


internal static class RibbonWindowExtensions
{
    [SecurityCritical,
    SecuritySafeCritical]
    internal static void HideButtons(this RibbonWindow window)
    {
        IntPtr hwnd = new WindowInteropHelper(window).Handle;

        int lStyle = NativeMethods.GetWindowLong(hwnd, NativeMethods.WindowStyles.GWL_STYLE);
        lStyle &= ~(NativeMethods.WindowStyles.WS_CAPTION | 
                    NativeMethods.WindowStyles.WS_THICKFRAME | 
                    NativeMethods.WindowStyles.WS_MINIMIZEBOX | 
                    NativeMethods.WindowStyles.WS_MAXIMIZEBOX);

        NativeMethods.SetWindowLong(hwnd, NativeMethods.WindowStyles.GWL_STYLE, lStyle);

        int lExStyle = NativeMethods.GetWindowLong(hwnd, NativeMethods.WindowStyles.GWL_EXSTYLE);
        lExStyle &= ~(NativeMethods.WindowStyles.WS_EX_DLGMODALFRAME | 
                      NativeMethods.WindowStyles.WS_EX_CLIENTEDGE | 
                      NativeMethods.WindowStyles.WS_EX_STATICEDGE);
        
        NativeMethods.SetWindowLong(hwnd, NativeMethods.WindowStyles.GWL_EXSTYLE, lExStyle);

        NativeMethods.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, NativeMethods.SWP.FRAMECHANGED | 
                                                                  NativeMethods.SWP.NOMOVE | 
                                                                  NativeMethods.SWP.NOSIZE | 
                                                                  NativeMethods.SWP.NOZORDER);
    }

    internal static void EnableClassicStyle(this RibbonWindow window) 
    {
        IntPtr hwnd = new WindowInteropHelper(window).Handle;

        if (hwnd != IntPtr.Zero)
        {
            EnableDefaulWindow(window);
        }
        else 
        {
            window.Loaded += EnableDefaultStyleOnLoaded;
        }

    }

    internal static void EnableDefaultStyleOnLoaded(object sender, EventArgs e) 
    {
        RibbonWindow window = sender as RibbonWindow;
        window.Loaded -= EnableDefaultStyleOnLoaded;
        EnableDefaulWindow(window);
       
    }

    [SecurityCritical,
    SecuritySafeCritical]
    internal static void EnableDefaulWindow(RibbonWindow window) 
    {
        IntPtr hwnd = new WindowInteropHelper(window).Handle;

        HwndSource src = HwndSource.FromHwnd(hwnd);
        //// settings the following value is necassary to have a transparent glass background instead of black:
        src.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);

        int lStyle = NativeMethods.GetWindowLong(hwnd, NativeMethods.WindowStyles.GWL_STYLE);
        lStyle |= NativeMethods.WindowStyles.WS_CAPTION | NativeMethods.WindowStyles.WS_THICKFRAME | NativeMethods.WindowStyles.WS_MINIMIZEBOX | NativeMethods.WindowStyles.WS_MAXIMIZEBOX;

        NativeMethods.SetWindowLong(hwnd, NativeMethods.WindowStyles.GWL_STYLE, lStyle);

        int lExStyle = NativeMethods.GetWindowLong(hwnd, NativeMethods.WindowStyles.GWL_EXSTYLE);

        lExStyle |= NativeMethods.WindowStyles.WS_EX_DLGMODALFRAME | NativeMethods.WindowStyles.WS_EX_STATICEDGE;
        NativeMethods.SetWindowLong(hwnd, NativeMethods.WindowStyles.GWL_EXSTYLE, lExStyle);
        
        NativeMethods.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, NativeMethods.SWP.FRAMECHANGED | NativeMethods.SWP.NOMOVE | NativeMethods.SWP.NOSIZE | NativeMethods.SWP.NOZORDER);
        
        NativeMethods.MARGINS margins = new NativeMethods.MARGINS();
        margins.cxLeftWidth = (int)window._resizeFrameBorderSize;
        margins.cxRightWidth = (int)window._resizeFrameBorderSize;
        margins.cyTopHeight = (int)System.Windows.SystemParameters.CaptionHeight + (int)window._resizeFrameBorderSize;
        margins.cyBottomHeight = (int)window._resizeFrameBorderSize;
        NativeMethods.DwmExtendFrameIntoClientArea(hwnd, ref margins);
        
    }
}